package com.transaction.common.util;

import java.util.Random;

public class IdCardUtil {

    static final String COUNTY_CODES = "640000,640100,640104,640105,640106,640121,640122,640181,640200,640202,640205," +
            "640221,640300,640302,640303,640323,640324,640381,640400,640402,640422,640423,640424,640425,640500,640502," +
            "640521,640522,650000,650100,650102,650103,650104,650105,650106,650107,650109,650121,650200,650202,650203," +
            "650204,650205,652100,652101,652122,652123,652200,652201,652222,652223,652300,652700,652800,652900,653000," +
            "653100,653125,653200,653226,654200,654202,654300,659001,659002,659003,659004,820000";

    static final Random random = new Random();

    /**
     * 生成身份证号码
     * @return
     */
    public static String generate(){
        return buildIdentityNo(buildPrefix17(randomCounty(),randomBirthDay(),randomLocation(),randomSex()));
    }

    /**
     * 随机一个城市
     */
    static String randomCounty(){
        String[] countyCodes = COUNTY_CODES.split(",");
        String countryCode = countyCodes[random.nextInt(countyCodes.length)];
        return countryCode;
    }

    /**
     * 随机一个出生日期
     */
    static String randomBirthDay() {
        StringBuilder birthDay = new StringBuilder();
        Integer year = 1921 + random.nextInt(90);
        Integer month = random.nextInt(12) + 1;
        Integer day = random.nextInt(30) + 1;
        if (month == 2) {
            day = 28;
        }

        birthDay.append(year);

        if(String.valueOf(month).length() < 2){
            birthDay.append("0").append(month);
        }else{
            birthDay.append(month);
        }

        if(String.valueOf(day).length() < 2){
            birthDay.append("0").append(day);
        }else{
            birthDay.append(day);
        }

        return birthDay.toString();
    }

    /**
     * 随机一个警局所在地
     */
    public static String randomLocation(){
        return String.valueOf(random.nextInt(90) + 10);
    }

    /**
     * 随机一个性别
     */
    public static String randomSex(){
        return String.valueOf(random.nextInt(10));
    }

    /**
     * 组装身份证前17位数字
     */
    static String buildPrefix17(String countryCode,
                                 String birthday,
                                 String location,
                                 String sex) {

        StringBuilder prefix = new StringBuilder();
        prefix.append(countryCode)
                .append(birthday)
                .append(location)
                .append(sex);
        return prefix.toString();
    }

    /**
     * 根据前17位生成最后一位，并组装
     */
    static String buildIdentityNo(String prefix) {
        //1.step1,2
        Integer sum = executeStepOneAndTwo(prefix);
        //2.step3,4
        String identityNo = executeStepThreeAndFour(prefix,sum);

        return identityNo;
    }

    /**
     * 计算身份证前17位的和
     * 第一步：
     * 将身份证号码的第1位数字与7相乘；
     * 将身份证号码的第2位数字与9相乘；
     * 将身份证号码的第3位数字与10相乘；
     * 将身份证号码的第4位数字与5相乘；
     * 将身份证号码的第5位数字与8相乘；
     * 将身份证号码的第6位数字与4相乘；
     * 将身份证号码的第7位数字与2相乘；
     * 将身份证号码的第8位数字与1相乘；
     * 将身份证号码的第9位数字与6相乘；
     * 将身份证号码的第10位数字与3相乘；
     * 将身份证号码的第11位数字与7相乘；
     * 将身份证号码的第12位数字与9相乘；
     * 将身份证号码的第13位数字与10相乘；
     * 将身份证号码的第14位数字与5相乘；
     * 将身份证号码的第15位数字与8相乘；
     * 将身份证号码的第16位数字与4相乘；
     * 将身份证号码的第17位数字与2相乘。
     *
     * 第二步：将第一步身份证号码1~17位相乘的结果求和，全部加起来。
     */
    static Integer executeStepOneAndTwo(String prefix) {
        int length = prefix.length();
        int sum = 0;
        for(int i = 0; i < length; i++){
            switch (i){
                case 0 :
                case 10 :
                    sum += (prefix.charAt(i)-'0') * 7;break;

                case 2 :
                case 12 :
                    sum += (prefix.charAt(i)-'0') * 10;break;

                case 3 :
                case 13 :
                    sum += (prefix.charAt(i)-'0') * 5;break;

                case 4 :
                case 14 :
                    sum += (prefix.charAt(i)-'0') * 8;break;

                case 5 :
                case 15 :
                    sum += (prefix.charAt(i)-'0') * 4;break;

                case 6 :
                case 16 :
                    sum += (prefix.charAt(i)-'0') * 2;break;

                case 1 :
                case 11 :
                    sum += (prefix.charAt(i)-'0') * 9;break;

                case 7 : sum += (prefix.charAt(i)-'0') * 1;break;
                case 8 : sum += (prefix.charAt(i)-'0') * 6;break;
                case 9 : sum += (prefix.charAt(i)-'0') * 3;break;
            }
        }
        return sum;
    }

    /**
     * 计算最后一位
     * 第三步：用第二步计算出来的结果除以11，
     * 这样就会出现余数为0，余数为1，余数为2，余数为3，余数为4，余数为5，余数为6，余数为7，余数为8，余数为9，
     * 余数为10共11种可能性。
     *
     * 第四步：
     * 如果余数为0，那对应的最后一位身份证的号码为1；
     * 如果余数为1，那对应的最后一位身份证的号码为0；
     * 如果余数为2，那对应的最后一位身份证的号码为X；
     * 如果余数为3，那对应的最后一位身份证的号码为9；
     * 如果余数为4，那对应的最后一位身份证的号码为8；
     * 如果余数为5，那对应的最后一位身份证的号码为7；
     * 如果余数为6，那对应的最后一位身份证的号码为6；
     * 如果余数为7，那对应的最后一位身份证的号码为5；
     * 如果余数为8，那对应的最后一位身份证的号码为4；
     * 如果余数为9，那对应的最后一位身份证的号码为3；
     * 如果余数为10，那对应的最后一位身份证的号码为2。
     */
    static String executeStepThreeAndFour(String prefix, Integer sum) {
        String suffix = "";
        int remainder = sum % 11;
        switch (remainder){
            case 0 : suffix = "1";break;
            case 1 : suffix = "0";break;
            case 2 : suffix = "X";break;
            case 3 : suffix = "9";break;
            case 4 : suffix = "8";break;
            case 5 : suffix = "7";break;
            case 6 : suffix = "6";break;
            case 7 : suffix = "5";break;
            case 8 : suffix = "4";break;
            case 9 : suffix = "3";break;
            case 10 : suffix = "2";break;
        }
        prefix += suffix;
        return  prefix;
    }
}
